import React, {Component} from 'react';
import {
    StyleSheet,
    View,
    FlatList,
    Text,
    Button,
    ToastAndroid,
} from 'react-native';
import * as Color from "../constant/Color";

const ITEM_HEIGHT = 50;

/**
 * ItemSeparatorComponent：  分割线组件，
 * ListFooterComponent：     结尾组件
 * ListHeaderComponent：     头组件
 * data：                    列表数据
 * horizontal：              设置为true则变为水平列表。
 * numColumns：              列数 组件内元素必须是等高的,无法支持瀑布流布局
 * columnWrapperStyle：      numColumns大于1时，设置每行的样式
 * getItemLayout：           如果我们知道行高可以用此方法节省动态计算行高的开销。
 * refreshing：              是否正在加载数据
 * onRefresh：               设置此属性需要一个标准的 RefreshControl 控件，刷新数据
 * renderItem：              渲染每个组件
 * onEndReachedThreshold     滑动到距离底部（xx）的距离（阈值）
 * onEndReached              onEndReached：在Android环境下是当滑动到距离底部（xx）距离时触发的，已经滑动到底部后已经不满足距离底部xx的条件，不会再次触发onEndReached（）事件的。因为苹果的可滑动组件可以拉到底部之后让组件距离底部再拉伸一段距离，但是安卓上可滑动组件上拉倒底部之后不能再拉动
 *
 * onViewableItemsChanged：
 * ---当一个新的Item渲染或者隐藏 的时候调用此方法。参数：info: {viewableItems: Array, changed: Array} viewableItems：当前可见的Item，changed：渲染或者隐藏的Item。
 * scrollToEnd({params?: ?{animated?: ?boolean}})：
 * ---滚动到末尾，如果不设置getItemLayout属性的话，可能会比较卡。
 * scrollToIndexparams: {animated?: ?boolean, index: number, viewPosition?: number}：
 * ---滚动到制定的位置
 * scrollToOffset(params: {animated?: ?boolean, offset: number})：
 * ---滚动到指定的偏移的位置。
 */
export default class FlatListDemo extends Component {

    _mFlatList;

    constructor(props){
        super(props);
        this.state = {
            /** 是否正在刷新 */
            mIsRefresh  : false,
            /** 数据源 */
            mDatas      : this._getDatas(0),
            /** foot提示信息 */
            loadMoreInfo:'正在加载',
        }
    }

    /**
     * 将列表元素和数据结合在一起，生成列表。
     * @param item 是data属性中的每个列表的数据（ Array<object> 中的 object) 。
     */
    _renderItem(item){
        let txt = '第' + item.index + '个' + ' title=' + item.item.title;
        let bgColor = item.index % 2 === 0 ? Color.white : Color.lightGray;
        return <Text style={[{flex: 1, height: ITEM_HEIGHT, backgroundColor: bgColor}, styles.txt]}>{txt}</Text>
    };

    /** 头 */
    _header(){
        return <Text style={[styles.txt,{backgroundColor:'black'}]}>这是头部</Text>;
    };

    /** 尾 */
    _footer(){
        return <Text style={[styles.txt,{backgroundColor:'black'}]}>{this.state.loadMoreInfo}</Text>;
    };

    /** 分割线 */
    _separator(){
        return <View style={{height:1,backgroundColor:Color.darkGray}}/>;
    };

    /**
     * 可选优化项。但是实际测试中，如果不做该项优化，性能会差很多。
     * 所以强烈建议做此项优化！如果不做该项优化，每个列表都需要事先渲染一次，动态地取得其渲染尺寸，然后再真正地渲染到页面中。
     * 如果预先知道列表中的每一项的高度(ITEM_HEIGHT)和其在父组件中的偏移量(offset)和位置(index)，就能减少一次渲染。
     * 这是很关键的性能优化点
     * @param data
     * @param index
     * @returns {{length: number, offset: number, index: *}}
     */
    getItemLayout = (data, index) => {
        return {length: ITEM_HEIGHT, offset: (ITEM_HEIGHT+2) * index, index}
    };

    render() {
        return (
            <View style={{flex:1}}>
                <Button title='滚动到指定位置' onPress={()=>{
                    //this._mFlatList.scrollToEnd();
                    this._mFlatList.scrollToIndex({viewPosition:0,index:8});
                    // this._mFlatList.scrollToOffset({animated: true, offset: 2000});
                }}/>
                <View style={{flex:1}}>
                    <FlatList
                        ref={(flatList)=>this._mFlatList = flatList}
                        ListHeaderComponent={this._header()}
                        ListFooterComponent={this._footer()}

                        data={this.state.mDatas}
                        renderItem={this._renderItem}
                        ItemSeparatorComponent={this._separator}
                        keyExtractor={(item,index)=>("index"+index+item)}

                        //numColumns ={3}
                        //columnWrapperStyle={{borderWidth:2,borderColor:'black',paddingLeft:20}}

                        //horizontal={true}

                        refreshing={this.state.mIsRefresh}
                        onRefresh={this._onRefresh}

                        getItemLayout={this.getItemLayout}

                        onEndReachedThreshold={0.1}
                        onEndReached={this._onReachEnd}
                        // onEndReached={(info)=>{
                        //     this._onReachEnd(info);
                        // }}

                        //onViewableItemsChanged={(info)=>{
                        //console.warn(info);
                        //}}
                    />
                </View>
            </View>
        );
    }

    /**
     * 和 ListView 不同，它没有特殊的 DataSource 数据类型作为传入参数。
     * 它接收的仅仅只是一个 Array<object> 作为参数。
     * 参数数组中的每一项，需要包含 key 值作为唯一标示。数据结构如下：
     * [{title: 'Title Text', key: 'item1'}]
     */
    _getDatas(index){
        let data = [];
        for (let i = index; i < index + 10; i++) {
            data.push({key: i, title: i + ''});
        }
        return data;
    }

    /** 下拉时促发 */
    _onRefresh = () => {
        if(this.state.mIsRefresh) return;
        ToastAndroid.show('正在刷新中.... ', ToastAndroid.SHORT);
        this.setState({
            mIsRefresh : true,
        });

        let timer = setTimeout(() => {
            this.setState({
                mIsRefresh : false,
            });
            clearTimeout(timer);
        }, 1000)
    };

    /** 拉到底部时促发 */
    _onReachEnd = () => {
        if (this.state.mDatas.length >= 58) {
            this.setState({
                loadMoreInfo : '已经到底了',
            });
            return;
        }
        // ToastAndroid.show('继续拉取', ToastAndroid.SHORT);
        this.setState({
            mDatas: this.state.mDatas.concat(this._getDatas(this.state.mDatas.length)),
        });
    };
}

const styles = StyleSheet.create({
    txt: {
        textAlign: 'center',
        textAlignVertical: 'center',
        color: Color.darkGray,
        fontSize: 20,
    }
});
